var Utils = require('geoUtils');

var LogicUtils = {
    Mode: cc.Enum({
        // 任意特征匹配成功
        ANY: 0,
        // 所有特征完全相同
        ALL: 1
    }),
    /**
     * 
     * @param {*} items 数组类型
     * @param {*} mode 选择匹配模式
     * @param {*} restriction 设置items应该有那些特征
     * @param {*} featureFunc items中的item获得特征值的方法   此方法参数限制为item  返回值限制为 特征值数组【小，红，圆】
     */
    validateFeatures(items, mode/* Utils.logic.Mode.ALL */, restriction, featureFunc) {
        // if (mode === null || mode === undefined)
        //     mode = LogicUtils.Mode.ANY;
        //
        if (restriction == null)
            return LogicUtils.validateFeaturesInItems(items, mode, featureFunc);
        else
            return LogicUtils.validateFeaturesWithRestriction(items, mode, restriction, featureFunc);
    },
    /**
     * 参数要求同validateFeatures函数的要求
     * 此函数只判断items数组中的所有元素是否有共同特征值
     * 不管是ALL模式还是ANY模式 只要items不变则返回值中的 commonFeatures 和 differentFeatures不变
     * isValid
     *      在ALL模式下 当所有items的特征值均相同时为true items【0】的特征值【大红圆】items【1】的特征值【大红圆】
     *      在ANY模式下 所有items的特征值存在相同特征时为true items【0】的特征值【大红圆】items【1】的特征值【大绿方】
     * isValid为
     *      true则将所有items加入validItems中
     *      false则将所有items加入invalidItems中
     * items =[cc.Node,cc.Node,cc.Node]
     * 第一个node的名字为 node?Tags=small red circle
     * 第二个node的名字为 node?Tags=small red square 
     * 第二个node的名字为 node?Tags=small green square 
     * 
     * mode = LogicUtils.Mode.ALL   
     * 
     * featureFunc = function(item){
     *      return Utils.node.getFeatures(item,'Tags');
     * }
     * 
     * var result = validateFeatures(items, mode, featureFunc)
     * result = {
     *      isValid = false;
     *      commonFeatures = [small];
     *      differentFeatures = [red,green,square,circle]
     *      validItems = [];   
     *      invalidItems = [cc.Node,cc.Node,cc.Node];   
     * }
     * 
     * 如果更换mode= LogicUtils.Mode.ANY
     * 其他不变 
     * result = {
     *      isValid = true;
     *      commonFeatures = [small];
     *      differentFeatures = [red,green,square,circle]
     *      validItems = [cc.Node,cc.Node,cc.Node];   
     *      invalidItems = [];   
     * }
     * 
     * @param {*} items 
     * @param {*} mode 
     * @param {*} featureFunc 
     */
    validateFeaturesInItems(items, mode, featureFunc) {
        var ret = {
            // 注释
            isValid: false,
            // 注释
            commonFeatures: [],
            // 注释
            differentFeatures: [],
            // 注释
            validItems: [],
            // 注释
            invalidItems: []
        };
        // 判定过程
        var featureDyadic = LogicUtils._itemArrayToDyadic(items, featureFunc);
        var featureObj = Utils.array.countMatch(featureDyadic);
        for (var attr in featureObj) {
            if (featureObj[attr] == items.length) {
                ret.commonFeatures.push(attr);
            }
            else
                ret.differentFeatures.push(attr);
        }
        if (mode == LogicUtils.Mode.ANY) {
            if (ret.commonFeatures.length > 0) {
                ret.isValid = true;
                ret.validItems = items;
            }
            else {
                ret.isValid = false;
                ret.invalidItems = items;
            }
        }
        else if (mode == LogicUtils.Mode.ALL) {
            //假设所有item中的特征的数量相同  item1【大红圆】 item2【小绿方】
            if (ret.commonFeatures.length == featureDyadic[0].length) {
                ret.isValid = true;
                ret.validItems = items;
            }
            else {
                ret.isValid = false;
                ret.invalidItems = items;
            }
        }

        //
        return ret;

    },
    /**
     * 
     * 例1  模式采用ALL   在此模式下只有 item的特征值包含全部的 restriction 此item才判断为正确 
     * 添加到validItems数组中   否则添加到invalidItems数组中
     * 
     * items =[cc.Node,cc.Node,cc.Node]
     * 第一个node的名字为 node?Tags=small red circle
     * 第二个node的名字为 node?Tags=small red square 
     * 第二个node的名字为 node?Tags=small green square 
     * 
     * mode = LogicUtils.Mode.ALL
     * 
     * restriction = 'red'
     * 
     * featureFunc = function(item){
     *      return Utils.node.getFeatures(item,'Tags');
     * }
     * 
     * var result = validateFeatures(items, mode, restriction, featureFunc)
     * result = {
     *      isValid = false;
     *      commonFeatures = [red];
     *      differentFeatures = [small,circle]
     *      validItems = [cc.Node,cc.Node];   items中的特征值为 小红圆 小红方的节点
     *      invalidItems = [cc.Node];    items中特征值为 小绿方的节点
     * }
     * 
     * 
     * 
     * 例2 模式采用ANY   在此模式下只有 item的特征值包含 restriction 中的任一特征值item判断为正确 
     * 添加到validItems数组中   否则添加到invalidItems数组中
     * 
     * items =[cc.Node,cc.Node,cc.Node]
     * 第一个node的名字为 node?Tags=big red circle
     * 第二个node的名字为 node?Tags=small red square 
     * 第二个node的名字为 node?Tags=big green square 
     * 
     * mode = LogicUtils.Mode.ALL
     * 
     * restriction = 'small red circle'
     * 
     * featureFunc = function(item){
     *      return Utils.node.getFeatures(item,'Tags');
     * }
     * 
     * var result = validateFeatures(items, mode, restriction, featureFunc)
     * result = {
     *      isValid = false;
     *      commonFeatures = [];
     *      differentFeatures = [big,small,red,green,square,circle]
     *      validItems = [cc.Node,cc.Node];   items中的特征值为 大红圆 小红方的节点
     *      invalidItems = [cc.Node];    items中特征值为 大绿方的节点
     * }
     * 
     * 参数要求同validateFeatures函数的要求
     * @param {*} items 
     * @param {*} mode 
     * @param {*} restriction 
     * @param {*} featureFunc 
     */
    validateFeaturesWithRestriction(items, mode, restriction, featureFunc) {
        var ret = {
            // 注释
            isValid: false,
            // 注释
            commonFeatures: [],
            // 注释
            differentFeatures: [],
            // 注释
            validItems: [],
            // 注释
            invalidItems: []
        };


        // 判定过程
        items.forEach(item => {
            var timesObj = LogicUtils._getRightOrWrongTimes(item, restriction, featureFunc);

            //添加匹配成功的特征值
            var timesObjVF = timesObj.validFeatures;
            for (var i = 0; i < timesObjVF.length; i++) {
                var validFeature = timesObjVF[i];
                var index = Utils.array.indexOf(ret.commonFeatures, validFeature);
                if (index == -1) {
                    ret.commonFeatures.push(validFeature);
                }
            }




            if (mode == LogicUtils.Mode.ANY) {
                if (timesObj.rightTimes > 0) {
                    ret.validItems.push(item);
                }
                else {
                    ret.invalidItems.push(item);
                }
            }
            else if (mode == LogicUtils.Mode.ALL) {
                if (timesObj.wrongTimes > 0) {
                    ret.invalidItems.push(item);
                }
                else {
                    ret.validItems.push(item);
                }
            }
        });

        //获得不同的特征值
        var featureDyadic = LogicUtils._itemArrayToDyadic(items, featureFunc);
        //添加一行restriction的特征值
        featureDyadic.push(restriction);

        var featuresObj = Utils.array.countMatch(featureDyadic);
        for (var attr in featuresObj) {
            var index = Utils.array.indexOf(ret.commonFeatures, attr);
            if (index == -1) {
                ret.differentFeatures.push(attr);
            }
        }
        // //获取共同特征
        // var itemsFeatures = LogicUtils.validateFeaturesInItems(items, mode, featureFunc);
        // var featuresObj = Utils.array.countMatch([itemsFeatures.commonFeatures, restriction]);
        // for (var attr in featuresObj) {
        //     if (featuresObj[attr] < 2) {
        //         if (Utils.array.indexOf(itemsFeatures.differentFeatures, attr) == -1) {
        //             itemsFeatures.differentFeatures.push(attr);
        //         }
        //         Utils.array.remove(itemsFeatures.commonFeatures, attr);
        //     }
        // }
        // ret.commonFeatures = itemsFeatures.commonFeatures;
        // ret.differentFeatures = itemsFeatures.differentFeatures;
        //
        return ret;

    },
    /**
    * 将items数组中的各个item的特征值整合成为二维数组
    * @param {} items 
    */
    _itemArrayToDyadic(items, featureFunc) {
        var dyadic = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            var feature = featureFunc(item);
            dyadic.push(feature);
        }
        return dyadic;
    },
    /**
    * 判断item与restriction的特征值有几个相同几个不同
    * 组【大】      元素【大红圆】    rightTimes ==1  wrongTimes == 0；
    * 组【大红圆】  元素【大红方】    rightTimes == 2 wrongTimes == 1；
    * 组【大红圆】  元素【大】         rightTimes == 1 wrongTimes ==2；
    * 组【大红圆】  元素【小绿方】     rightTimes==0 wrongTimes==3；
    * @param {*} item
    * @param {*} restriction
    * @param {function} featureFunc
    */
    _getRightOrWrongTimes(item, restriction, featureFunc) {

        //记录错误次数
        var wrongTimes = 0;
        //记录正确次数
        var rightTimes = 0;
        //记录匹配成功的特征
        var validFeatures = [];
        // //记录匹配失败的特征
        // var invalidFeatures = [];

        //获得item的特征值
        var itemFeatures = featureFunc(item);
        //获得要restriction的特征值数组
        var restrictionFeatures = restriction;
        //循环的取出要判定的restriction的特征值查看能否在item的特征值数组中找到
        for (var i = 0; i < restrictionFeatures.length; i++) {
            var restrictionTag = restrictionFeatures[i];
            var index = Utils.array.indexOf(itemFeatures, restrictionTag);
            if (index > -1) {
                validFeatures.push(restrictionTag);
                rightTimes++;
            }
            else
                wrongTimes++;
        }
        return { rightTimes, wrongTimes, validFeatures };
    },

    /**
     * 将含有特征值的数组的特征值一般化   
     * 找到原型特征item数组 
     * 和当前特征一般化的特征字符串
     * 特征字符串用item在原型item数组中的序号表示
     * @param {*} items 
     * @param {*} getFeatFunc 
     */
    getArrayPattern(items, getFeatFunc) {
        var patternObj = {
            //一般化的特征字符串
            pattern: '', //  改名为pattern
            //特征原型
            encode: [],// encode
        };
        items.forEach(item => {
            //检查每一个item在patternObj的encode中的序号
            LogicUtils.checkOneIsInPattern(item, patternObj, getFeatFunc);
        });
        return patternObj;
    },
    /**
     * 检查item是否在patternObj的encode中 
     * 如果不在则将item添加到encode中
     * pattern后面添加当前item在encode中的序号
     * @param {*} item 
     * @param {*} patternObj 
     * @param {*} getFeatFunc 
     */
    checkOneIsInPattern(item, patternObj, getFeatFunc) {
        //
        var encode = patternObj.encode;
        if (getFeatFunc == null) {
            getFeatFunc = (e) => e;
        }
        //记录序号
        var i = 0;
        //获得item特征
        var feature = getFeatFunc(item);
        for (; i < encode.length; i++) {
            //获得原型特征
            var proFeat = getFeatFunc(encode[i])
            if (feature == proFeat) {
                //找到原型
                patternObj.pattern = patternObj.pattern + ' ' + i;
                //结束本次探索
                return;
            }
        }
        //未找到原型  将item加入原型队列
        patternObj.encode.push(item);
        //添加tags
        patternObj.pattern = patternObj.pattern + ' ' + i;
    },
};

module.exports = LogicUtils;